// 全局 WebSocket 单例（支持多房间、全局 group、心跳、重连、事件分发、已读、typing、全局通知）
let ws = null;
let wsUrl = '';
let heartbeatTimer = null;
let reconnectTimer = null;
let listeners = {
  chat_message: [],
  history_messages: [],
  messages_read: [],
  user_typing: [],
  connection_established: [],
  global_message: [],
  error: [],
  pong: [],
};
let currentRoomId = null;
let token = null;

function getWsUrl(roomId, isGlobal = false) {
  token = localStorage.getItem('token');
  if (isGlobal) {
    return `ws://localhost:8000/ws/chat/global/?token=${token}`;
  }
  return `ws://localhost:8000/ws/chat/${roomId}/?token=${token}`;
}

function clearTimers() {
  if (heartbeatTimer) {
    clearInterval(heartbeatTimer);
    heartbeatTimer = null;
  }
  if (reconnectTimer) {
    clearTimeout(reconnectTimer);
    reconnectTimer = null;
  }
}

function notifyListeners(type, payload) {
  console.log('[notifyListeners]', type, listeners[type]);
  (listeners[type] || []).forEach(fn => fn(payload));
}

export function addWsListener(type, fn) {
  if (listeners[type] && !listeners[type].includes(fn)) {
    listeners[type].push(fn);
  }
}

export function removeWsListener(type, fn) {
  if (listeners[type]) {
    listeners[type] = listeners[type].filter(f => f !== fn);
  }
}

// 递归安全解析JSON，兼容多重嵌套
function safeJsonParse(data) {
  let result = data;
  let count = 0;
  while (typeof result === 'string' && count < 5) {
    try {
      result = JSON.parse(result);
    } catch (e) {
      break;
    }
    count++;
  }
  return result;
}

export function connectRoomWs(roomId) {
  if (!roomId || roomId === 'null' || roomId === 'undefined') {
    console.error('[WS连接] roomId无效，禁止连接', roomId);
    return null;
  }
  token = localStorage.getItem('token');
  wsUrl = getWsUrl(roomId);
  // 先赋值
  currentRoomId = roomId;
  if (ws && ws.readyState !== 3 && currentRoomId === roomId) return ws;
  closeWs();
  ws = new window.WebSocket(wsUrl);

  ws.onopen = () => {
    // 再次确保赋值
    currentRoomId = roomId;
    clearTimers();
    heartbeatTimer = setInterval(() => {
      if (ws.readyState === 1) {
        ws.send(JSON.stringify({ type: 'ping' }));
      }
    }, 30000);
  };

  ws.onclose = () => {
    clearTimers();
    // 自动重连
    reconnectTimer = setTimeout(() => {
      connectRoomWs(currentRoomId);
    }, 3000);
  };

  ws.onerror = () => {
    clearTimers();
  };

  ws.onmessage = (event) => {
    try {
      const data = JSON.parse(event.data);
      if (data.type && listeners[data.type]) {
        notifyListeners(data.type, data);
      }
    } catch (e) {
      notifyListeners('error', { message: '消息解析失败', raw: event.data });
    }
  };
  return ws;
}

export function connectGlobalWs() {
  token = localStorage.getItem('token');
  wsUrl = getWsUrl('', true);
  currentRoomId = 'global';
  console.log('[WS连接] connectGlobalWs', { wsUrl, token, time: new Date().toISOString() });
  // 只允许一个全局 ws
  if (ws && ws.readyState !== 3 && currentRoomId === 'global') return ws;
  closeWs();
  ws = new window.WebSocket(wsUrl);

  ws.onopen = () => {
    clearTimers();
    heartbeatTimer = setInterval(() => {
      if (ws.readyState === 1) {
        ws.send(JSON.stringify({ type: 'ping' }));
      }
    }, 30000);
  };
  ws.onclose = () => {
    clearTimers();
    reconnectTimer = setTimeout(() => {
      connectGlobalWs();
    }, 3000);
  };
  ws.onerror = () => {
    clearTimers();
  };
  ws.onmessage = (event) => {
    // 新增：打印原始消息内容，便于调试
    console.log('[全局WS原始消息]', event.data);
    let data;
    try {
      data = JSON.parse(event.data);
      // 新增：打印解析后的type和message字段
      console.log('[全局WS解析后]', { type: data.type, message: data.message });
      if (data.type && listeners[data.type]) {
        notifyListeners(data.type, data);
      }
    } catch (e) {
      notifyListeners('error', { message: '消息解析失败', raw: event.data });
    }
  };
  return ws;
}

export function sendWsMessage(data) {
  if (ws && ws.readyState === 1) {
    ws.send(JSON.stringify(data));
  }
}

export function closeWs() {
  if (ws) {
    ws.close();
    ws = null;
  }
  clearTimers();
  currentRoomId = null;
}

export function getCurrentRoomId() {
  return currentRoomId;
}

export function getWsInstance() {
  return ws;
} 